﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using MEF_Test.Bricks;
using MEF_Test.Bricks.Actions;
using MEF_Test.Contracts;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using OpenAction;
using Synology.AudioStationApi;

namespace MEF_Test.Module.AudioStation.Tests
{
    /// <summary>
    /// Summary description for DownloadsTests
    /// </summary>
    [TestClass]
    public class DownloadsTests
    {
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext { get; set; }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestInitialize]
        public void IoCInitialize()
        {
            var actionManagerMock = new Mock<IActionsManager>();
            actionManagerMock.Setup(o => o.ExportedActions).Returns(
                new ObservableCollection<Lazy<INodeAction, IDictionary<string, object>>>());
            IoC.Current.RegisterInstance(actionManagerMock.Object);
        }

        [TestMethod]
        public void DownloadResTest()
        {

            // Create Mocks for :
                // - Action Context Provider ( an open command )
                // - Action Context Providers Manager ( Representing the context providers for the commands, i.e. : OpenInXXX )
                // - Actions Manager : The one importing all the exported commands.
                // - MEF Container
 
            // Initialize IoC for :                 
                // - Actions Manager : The one importing all the exported commands.
                // - MEF Container

            var mockOpenActionContextProvider = new Mock<IOpenActionContextProvider>();
            mockOpenActionContextProvider.Setup(o => o.Supports(It.IsAny<IBrowserNodeViewModel>())).Returns(true);

            Stream stream = null;
            mockOpenActionContextProvider.Setup(o => o.Process(It.IsAny<IBrowserNodeViewModel>())).Callback<IBrowserNodeViewModel>(o=>
                                                                                                       {
                                                                                                           stream =((AudioStationTrackFileHandler)o.FileHandler).GetStream();                                                                                                           
                                                                                                       });
            
            var meContainer = new Mock<CompositionContainer>();
            IoC.Current.RegisterInstance(meContainer.Object);
            
            var mock = new Mock<IActionsManager>();
            
            IoC.Current.RegisterInstance(mock.Object);



            List<Lazy<IOpenActionContextProvider>> lazyOpenContextProviderList;
            lazyOpenContextProviderList = new List<Lazy<IOpenActionContextProvider>>();

            var lazyOpenContextProvider = new Lazy<IOpenActionContextProvider>(() => mockOpenActionContextProvider.Object);

            lazyOpenContextProviderList.Add(lazyOpenContextProvider);

            var dict = new Dictionary<string, object> { { "Action", "Open" } };
            var lazyAction = new Lazy<INodeAction, IDictionary<string, object>>(new Func<INodeAction>(() => new OpenAction.OpenAction(lazyOpenContextProviderList)), dict);
            
            var actions = new ObservableCollection<Lazy<INodeAction, IDictionary<string, object>>> {lazyAction};
            mock.Setup(o => o.ExportedActions).Returns(actions);

            // 1. Create a track
            // 2. Create a browserNode for this track
            // 3. Call the BrowserNode Open Action

            var track = new SynoTrack
            {
                IsTrack = true,
                Res = @"/volume1/music/iTunes Library/65daysofstatic/The Destruction of Small Ideals/01 When We Were Younger & Better.mp3"
            };

            // We need to inject an OpenContext ! ( in order to do so : we need to make it IoC-able. ) See OpenActionContextProvidersManager.Current
            var bn = new BrowserNodeViewModel<AudioStationFileHandler>(new AudioStationTrackFileHandler(AudioStationAction.Browse, track));
            bn.SupportedActions.Add(mockOpenActionContextProvider.Object);

            ((List<INodeAction>) bn.Actions).Add(lazyAction.Value);
            // TODO : Call the opencontext (how to retrieve it easily ?)
            ((OpenAction.OpenAction)bn.Actions.First()).ActivateCommand.Execute(bn);

            // Make sure the stream is valid
            Assert.IsNotNull(stream);
        }
    }
}
